package cc.eddic.practice.concurrency.impl;

import cc.eddic.practice.concurrency.LogItem;
import cc.eddic.practice.concurrency.LogItemParser;
import cc.eddic.practice.concurrency.LogParser;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.*;
@Slf4j
public class LogItemParserExecutorImpl implements LogParser {

    private final LogItemParserImpl logItemParser = new LogItemParserImpl();
    private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    private static final int LOG_FILE_COUNT = 255; // Adjust the count as needed

    public Map<String, List<LogItem>> parse(String folderName) {
        Map<String, List<LogItem>> resultMap = new ConcurrentHashMap<>();
        CountDownLatch latch = new CountDownLatch(LOG_FILE_COUNT);

        processFolder(new File(folderName), resultMap, latch);

        try {
            if(log.isInfoEnabled()) log.info("await latch");
            latch.await(); // Wait for all tasks to complete
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace(); // Handle the exception properly in a real application
        }

        executorService.shutdown();
        return resultMap;
    }

    private void processFolder(File folder, Map<String, List<LogItem>> resultMap, CountDownLatch latch) {
        if (folder.isDirectory()) {
            File[] files = folder.listFiles((dir, name) -> name.endsWith(".log"));

            if (files != null) {
                List<Callable<Void>> tasks = new ArrayList<>();

                for (File file : files) {
                    tasks.add(() -> {
                        String filePath = file.getAbsolutePath();
                        List<LogItem> logItems = new ArrayList<>();

                        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                            String line;
                            while ((line = reader.readLine()) != null) {
                                Optional<LogItem> optionalLogItem = logItemParser.parse(line);
                                optionalLogItem.ifPresent(logItems::add);
                            }
                        } catch (IOException e) {
                            e.printStackTrace(); // Handle the exception properly in a real application
                        }

                        resultMap.put(filePath, logItems);
                        latch.countDown(); // Decrement the latch count
                        return null;
                    });
                }

                try {
                    executorService.invokeAll(tasks);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace(); // Handle the exception properly in a real application
                }
            }

            File[] subFolders = folder.listFiles(File::isDirectory);
            if (subFolders != null) {
                for (File subfolder : subFolders) {
                    executorService.submit(() -> processFolder(subfolder, resultMap, latch));
                }
            }
        }
    }
}
